/*-------------------------------------------------------------------------
 * 处理嵌套条件语句的自动机状态堆栈。
 *
 * Copyright (c) 2000-2022, PostgreSQL Global Development Group
 *
 * src/fe_utils/conditional.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres_fe.h"

#include "fe_utils/conditional.h"

/*
 * 创建堆栈
 */
ConditionalStack
conditional_stack_create(void)
{
	ConditionalStack fc_cstack = pg_malloc(sizeof(ConditionalStackData));

	fc_cstack->head = NULL;
	return fc_cstack;
}

/*
 * 销毁堆栈中的所有元素。堆栈本身不会被释放。
 */
void conditional_stack_reset(ConditionalStack fc_cstack)
{
	if (!fc_cstack)
		return;					/* 此处无操作 */

	while (conditional_stack_pop(fc_cstack))
		continue;
}

/*
 * 销毁堆栈
 */
void conditional_stack_destroy(ConditionalStack fc_cstack)
{
	conditional_stack_reset(fc_cstack);
	free(fc_cstack);
}

/*
 * 创建一个新的条件分支。
 */
void conditional_stack_push(ConditionalStack fc_cstack, ifState fc_new_state)
{
	IfStackElem *fc_p = (IfStackElem *) pg_malloc(sizeof(IfStackElem));

	fc_p->if_state = fc_new_state;
	fc_p->query_len = -1;
	fc_p->paren_depth = -1;
	fc_p->next = fc_cstack->head;
	fc_cstack->head = fc_p;
}

/*
 * 销毁最顶部的条件分支。
 * 如果没有分支需要结束，则返回false。
 */
bool conditional_stack_pop(ConditionalStack fc_cstack)
{
	IfStackElem *fc_p = fc_cstack->head;

	if (!fc_p)
		return false;
	fc_cstack->head = fc_cstack->head->next;
	free(fc_p);
	return true;
}

/*
 * 返回当前堆栈深度，供调试使用。
 */
int conditional_stack_depth(ConditionalStack fc_cstack)
{
	if (fc_cstack == NULL)
		return -1;
	else
	{
		IfStackElem *fc_p = fc_cstack->head;
		int			fc_depth = 0;

		while (fc_p != NULL)
		{
			fc_depth++;
			fc_p = fc_p->next;
		}
		return fc_depth;
	}
}

/*
 * 获取当前堆栈顶部的状态。
 */
ifState
conditional_stack_peek(ConditionalStack fc_cstack)
{
	if (conditional_stack_empty(fc_cstack))
		return IFSTATE_NONE;
	return fc_cstack->head->if_state;
}

/*
 * 更改最顶部分支的状态。
 * 如果没有分支状态需要设置，则返回false。
 */
bool conditional_stack_poke(ConditionalStack fc_cstack, ifState fc_new_state)
{
	if (conditional_stack_empty(fc_cstack))
		return false;
	fc_cstack->head->if_state = fc_new_state;
	return true;
}

/*
 * 如果没有活动的\if-blocks，则返回true。
 */
bool conditional_stack_empty(ConditionalStack fc_cstack)
{
	return fc_cstack->head == NULL;
}

/*
 * 如果我们应该正常执行命令，则返回true；也就是说，当前的
 * 条件分支是活动的，或者没有打开的\if块。
 */
bool conditional_active(ConditionalStack fc_cstack)
{
	ifState		fc_s = conditional_stack_peek(fc_cstack);

	return fc_s == IFSTATE_NONE || fc_s == IFSTATE_TRUE || fc_s == IFSTATE_ELSE_TRUE;
}

/*
 * 在最顶部的堆栈条目中保存当前查询缓冲区长度。
 */
void conditional_stack_set_query_len(ConditionalStack fc_cstack, int fc_len)
{
	Assert(!conditional_stack_empty(fc_cstack));
	fc_cstack->head->query_len = fc_len;
}

/*
 * 从最顶部的堆栈条目中获取最后记录的查询缓冲区长度。
 * 如果没有堆栈或从未保存，则返回-1。
 */
int conditional_stack_get_query_len(ConditionalStack fc_cstack)
{
	if (conditional_stack_empty(fc_cstack))
		return -1;
	return fc_cstack->head->query_len;
}

/*
 * 在最顶部的堆栈条目中保存当前括号嵌套深度。
 */
void conditional_stack_set_paren_depth(ConditionalStack fc_cstack, int fc_depth)
{
	Assert(!conditional_stack_empty(fc_cstack));
	fc_cstack->head->paren_depth = fc_depth;
}

/*
 * 从最顶部的堆栈条目中获取最后记录的括号嵌套深度。
 * 如果没有堆栈或从未保存，则返回-1。
*/
int conditional_stack_get_paren_depth(ConditionalStack fc_cstack)
{
	if (conditional_stack_empty(fc_cstack))
		return -1;
	return fc_cstack->head->paren_depth;
}
